from fastapi import APIRouter, Depends, HTTPException, Path, Body, Query, status
from fastapi.responses import StreamingResponse
from typing import Dict, List, Any, Optional
import asyncio
from asyncio import TimeoutError

from app.services.chat_service import ChatService
from app.models.chat import ChatRequest, MessageFeedback
from app.core.logger import logger

router = APIRouter(prefix="/v1", tags=["对话"])

# 设置超时时间（秒）
DEFAULT_TIMEOUT = 30

# 依赖项：创建ChatService实例
def get_chat_service():
    return ChatService()

@router.post("/chat-messages", response_model=Dict[str, Any])
async def send_chat_message(
    chat_request: ChatRequest = Body(...),
    chat_service: ChatService = Depends(get_chat_service)
):
    """
    发送对话消息
    
    Args:
        chat_request: 聊天请求对象，包含以下字段：
            - query: 用户输入/提问内容
            - inputs: 允许传入App定义的各变量值
            - response_mode: streaming(流式)或blocking(阻塞)
            - user: 用户标识
            - conversation_id: 会话ID(可选)
            - files: 文件列表(可选)
            - auto_generate_name: 是否自动生成标题(可选)
    
    Returns:
        阻塞模式返回完整响应，流式模式返回SSE事件流
    """
    logger.debug(f"接收聊天请求: {chat_request.model_dump(exclude={'files'})}")
    
    try:
        # 检查请求参数
        if not chat_request.query:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="查询内容不能为空"
            )
            
        if not chat_request.user:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="用户标识不能为空"
            )
        
        if chat_request.response_mode == "streaming":
            try:
                result = await asyncio.wait_for(
                    chat_service.send_message(
                        query=chat_request.query,
                        user=chat_request.user,
                        conversation_id=chat_request.conversation_id,
                        inputs=chat_request.inputs,
                        files=chat_request.files,
                        response_mode="streaming"
                    ),
                    timeout=DEFAULT_TIMEOUT
                )
                
                return StreamingResponse(
                    chat_service.stream_chat_response(result),
                    media_type="text/event-stream"
                )
            except TimeoutError:
                logger.error("流式聊天请求处理超时")
                raise HTTPException(
                    status_code=status.HTTP_504_GATEWAY_TIMEOUT,
                    detail="请求处理超时，请稍后重试"
                )
        else:
            try:
                result = await asyncio.wait_for(
                    chat_service.send_message(
                        query=chat_request.query,
                        user=chat_request.user,
                        conversation_id=chat_request.conversation_id,
                        inputs=chat_request.inputs,
                        files=chat_request.files,
                        response_mode="blocking"
                    ),
                    timeout=DEFAULT_TIMEOUT
                )
                return result
            except TimeoutError:
                logger.error("阻塞聊天请求处理超时")
                raise HTTPException(
                    status_code=status.HTTP_504_GATEWAY_TIMEOUT,
                    detail="请求处理超时，请稍后重试或使用流式模式"
                )
    except HTTPException:
        # 重新抛出HTTPException，让FastAPI处理
        raise
    except Exception as e:
        logger.error(f"聊天消息处理失败: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, 
            detail=f"处理请求时发生错误: {str(e)}"
        )

@router.post("/chat-messages/{task_id}/stop", response_model=Dict[str, str])
async def stop_chat_message_generation(
    task_id: str = Path(..., description="任务ID"),
    user: str = Body(..., description="用户标识，必须和发送消息接口传入user保持一致"),
    chat_service: ChatService = Depends(get_chat_service)
):
    """
    停止响应
    
    仅支持流式模式。
    
    Args:
        task_id: 任务ID，可在流式返回Chunk中获取
        user: 用户标识，必须和发送消息接口传入user保持一致
        
    Returns:
        Dict[str, str]: 包含result字段，固定返回"success"
    """
    logger.debug(f"停止消息生成: task_id={task_id}, user={user}")
    
    try:
        # 检查参数
        if not task_id:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="任务ID不能为空"
            )
            
        if not user:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="用户标识不能为空"
            )
            
        try:
            result = await asyncio.wait_for(
                chat_service.stop_generation(task_id, user),
                timeout=5  # 停止操作超时设置较短
            )
            return {"result": "success"}
        except TimeoutError:
            logger.error(f"停止消息生成超时: task_id={task_id}")
            return {"result": "timeout", "message": "操作超时，但请求可能已发送"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"停止消息生成失败: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"停止生成时发生错误: {str(e)}"
        )

@router.post("/messages/{message_id}/feedbacks", response_model=Dict[str, str])
async def create_message_feedback(
    message_id: str = Path(..., description="消息ID"),
    feedback: MessageFeedback = Body(...),
    chat_service: ChatService = Depends(get_chat_service)
):
    """
    消息反馈（点赞）
    
    消息终端用户反馈、点赞，方便应用开发者优化输出预期。
    
    Args:
        message_id: 消息ID
        feedback: 反馈信息，包含：
            - rating: 点赞(like)、点踩(dislike)或撤销(null)
            - user: 用户标识
            - content: 反馈内容(可选)
            
    Returns:
        Dict[str, str]: 包含result字段，固定返回"success"
    """
    logger.debug(f"创建消息反馈: message_id={message_id}, feedback={feedback}")
    
    try:
        # 检查参数
        if not message_id:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="消息ID不能为空"
            )
            
        if not feedback.user:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="用户标识不能为空"
            )
            
        if feedback.rating not in ["like", "dislike", None]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="评分必须是like、dislike或null"
            )
        
        try:
            await asyncio.wait_for(
                chat_service.create_message_feedback(
                    message_id=message_id,
                    rating=feedback.rating,
                    user=feedback.user,
                    content=feedback.content
                ),
                timeout=5  # 反馈操作超时设置较短
            )
            return {"result": "success"}
        except TimeoutError:
            logger.error(f"创建消息反馈超时: message_id={message_id}")
            return {"result": "timeout", "message": "操作超时，但请求可能已处理"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"创建消息反馈失败: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"创建反馈时发生错误: {str(e)}"
        )

@router.get("/messages/{message_id}/suggested", response_model=Dict[str, Any])
async def get_suggested_questions(
    message_id: str = Path(..., description="消息ID"),
    user: str = Query(..., description="用户标识，由开发者定义规则，需保证用户标识在应用内唯一"),
    chat_service: ChatService = Depends(get_chat_service)
):
    """
    获取下一轮建议问题列表
    
    Args:
        message_id: 消息ID
        user: 用户标识，由开发者定义规则，需保证用户标识在应用内唯一
        
    Returns:
        Dict[str, Any]: 包含result和data字段:
            - result: "success"
            - data: 建议问题列表
    """
    logger.debug(f"获取建议问题: message_id={message_id}, user={user}")
    
    try:
        # 检查参数
        if not message_id:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="消息ID不能为空"
            )
            
        if not user:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="用户标识不能为空"
            )
        
        try:
            questions = await asyncio.wait_for(
                chat_service.get_suggested_questions(message_id, user),
                timeout=5  # 获取建议问题超时设置较短
            )
            return {
                "result": "success",
                "data": questions or []  # 确保返回空列表而不是None
            }
        except TimeoutError:
            logger.error(f"获取建议问题超时: message_id={message_id}")
            # 超时返回空列表
            return {
                "result": "timeout",
                "data": []
            }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取建议问题失败: {str(e)}")
        # 由于建议问题功能是辅助性的，失败时返回空列表比抛出500错误更友好
        return {
            "result": "error",
            "data": [],
            "message": str(e)
        }

@router.get("/messages", response_model=Dict[str, Any])
async def get_messages(
    conversation_id: str = Query(..., description="会话ID"),
    user: str = Query(..., description="用户标识，由开发者定义规则，需保证用户标识在应用内唯一"),
    first_id: Optional[str] = Query(None, description="当前页第一条聊天记录的ID，默认null"),
    limit: int = Query(20, description="一次请求返回多少条聊天记录，默认20条"),
    chat_service: ChatService = Depends(get_chat_service)
):
    """
    获取会话历史消息
    
    滚动加载形式返回历史聊天记录，第一页返回最新limit条，即：倒序返回。
    
    Args:
        conversation_id: 会话ID
        user: 用户标识
        first_id: 当前页第一条聊天记录的ID，默认null
        limit: 一次请求返回多少条聊天记录，默认20条
        
    Returns:
        Dict[str, Any]: 包含以下字段：
            - data: 消息列表
            - has_more: 是否存在下一页
            - limit: 返回条数
    """
    logger.debug(f"获取消息列表: conversation_id={conversation_id}, user={user}, first_id={first_id}, limit={limit}")
    
    try:
        # 检查参数
        if not conversation_id:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="会话ID不能为空"
            )
            
        if not user:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="用户标识不能为空"
            )
            
        # 限制limit范围，防止请求过大数据量
        if limit < 1:
            limit = 1
        elif limit > 100:
            limit = 100
        
        try:
            response = await asyncio.wait_for(
                chat_service.get_messages(
                    conversation_id=conversation_id,
                    user=user,
                    first_id=first_id,
                    limit=limit
                ),
                timeout=10  # 获取消息列表可能需要更多时间
            )
            return response
        except TimeoutError:
            logger.error(f"获取消息列表超时: conversation_id={conversation_id}")
            # 超时返回空数据结构
            return {
                "data": [],
                "has_more": False,
                "limit": limit
            }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取消息列表失败: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取消息列表时发生错误: {str(e)}"
        )

